package com.avicit.zipkinkafkaesserver.jobs;

import com.avicit.zipkinkafkaesserver.config.JobPropertiesConfig;
import com.avicit.zipkinkafkaesserver.dao.es.ZipkinInterfaceCountEsDao;
import com.avicit.zipkinkafkaesserver.dao.es.entity.ZipkinInterfaceCountES;
import com.avicit.zipkinkafkaesserver.entity.ZipkinInterfaceCount;
import com.avicit.zipkinkafkaesserver.service.SparkService;
import com.avicit.zipkinkafkaesserver.service.ZipkinInterfaceCountService;
import com.avicit.zipkinkafkaesserver.utils.TimeUtils;
import com.google.auto.value.AutoAnnotation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import scala.Tuple2;

import java.io.IOException;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class ZipkinInterfaceCountJob {

    @Autowired
    private ZipkinInterfaceCountService zipkinInterfaceCountService;

    @Autowired
    private SparkService sparkService;
    @Autowired
    private JobPropertiesConfig jobPropertiesConfig;

    public void interfaceCountJob() throws IOException {
        //开始时间获取
        Long startTime = zipkinInterfaceCountService.initStartTime();
        long endTime = startTime + jobPropertiesConfig.getFixedRateInterfaceCount();
        //job 执行的开始时间和 结束时间,也就是设置时间片
        Long jobStartTime = startTime;
        Long jobEndTime = endTime;

        //limit 取 Integer.MAX_VALUE
        //接口调用次数统计
        Map<String, Object> resultMap = sparkService.interfaceCountMap(startTime, endTime, 100);
        //获取统计结果
        List<Tuple2<String, Integer>> interfaceCount = (List<Tuple2<String, Integer>>) resultMap.get("countResult");
        if (interfaceCount.size() == 0) {//当前时间窗口没有数据，继续下一个时间窗口
            zipkinInterfaceCountService.updateStartTime(startTime + jobPropertiesConfig.getFixedRateInterfaceCount());
            jobPropertiesConfig.getConfigDB().setStatus(false);
            return;
        }
        //如果保存失败，不管是 批量失败，还是部分失败。每次的开始时间都是 根据批次号从es 里面获取的。
        if (endTime>=System.currentTimeMillis()) {//如果endTime>= 系统当前时间，取原始数据的时间作为结束时间
            //获取es 数据中 的最新时间
            Long lastEndTime = (Long) resultMap.get("lastEndTime");
            endTime = lastEndTime+1;//防止边界取重复
        }
        //设置系统初始值不可用
        jobPropertiesConfig.getConfigDB().setStatus(false);
        zipkinInterfaceCountService.saveToEs(interfaceCount, startTime, endTime,jobStartTime,jobEndTime);
    }


    /**
     * 将es 中的统计数据，一天的数据汇总写入数据库中
     * 一天执行一次,一个接口一天只有一条记录，今天统计昨天的
     */
    public void addInterfaceCountToDB() {
        //获取es 的统计信息
        List<ZipkinInterfaceCount> countResultFromEs = zipkinInterfaceCountService.getCountResultFromEs();
        //数据写入数据库
        zipkinInterfaceCountService.saveAllToDb(countResultFromEs);
    }


    /**
     * 统计接口调用次数
     * @throws IOException
     */
    @Scheduled(fixedRate = 100*60*1000)
    public void countAll() throws IOException, ParseException {
        log.info("countAll 统计接口调用次数 run interfaceCountJob ....");
        forDoInterfaceCount();
        log.info("countAll 统计接口调用次数 run interfaceCountJob end....");
        addInterfaceCountToDB();
        log.info("countAll 统计接口调用次数 run addInterfaceCountToDB end ....");

    }

    /**
     *循环统计 接口调用次数
     */
    public void forDoInterfaceCount() throws IOException, ParseException {

        for(int i= 0; i<1000; i++) {
            //开始时间获取
            Long startTime = zipkinInterfaceCountService.initStartTime();
            Date date = TimeUtils.getDate(startTime);
            int hour = TimeUtils.getHour(date);
            int minute = TimeUtils.getMinute(date);

            String toDay = TimeUtils.nowDateString();
            String yyyyMMdd = TimeUtils.getYyyyMMdd(startTime);

            if (toDay.equals(yyyyMMdd)) {return;}

            //退出
            if (hour >=23 && minute>=50) {
                startTime = startTime+ 24*60*60*1000;//时间+ 1天
                long nextDayZero = TimeUtils.getNextDayZero(startTime);// xx-xx-xx :00:00:00
                zipkinInterfaceCountService.updateStartTime(nextDayZero);
                break;
            }
            interfaceCountJob();
        }
    }
}
